#include "ai.h"
#include "output.h"
#include <cstdlib>
#include <climits>

// 初始化静态成员
int** AI::mark = nullptr;
QueueNode* AI::queueHead = nullptr;
QueueNode* AI::queueTail = nullptr;

void AI::initialize() {
    // 初始化标记数组
    mark = new int*[MapWidth / 2];
    for (int i = 0; i < MapWidth / 2; ++i) {
        mark[i] = new int[MapHeight];
    }
    resetMarks();
}

void AI::cleanup() {
    // 释放标记数组
    for (int i = 0; i < MapWidth / 2; ++i) {
        delete[] mark[i];
    }
    delete[] mark;
    mark = nullptr;
    
    // 清空队列
    clearQueue();
}

Direction AI::calculateNextMove(const SnakeNode* head, const Food& food) {
    // 重置标记
    resetMarks();
    
    // 标记蛇身(不可通过区域)
    const SnakeNode* current = head;
    while (current != nullptr) {
        mark[current->x / 2][current->y] = INT_MAX;
        current = current->next;
    }
    
    // 从食物开始标记路径
    markPath(food);
    
    // 寻找最佳方向
    return findBestDirection(head);
}

void AI::resetMarks() {
    for (int i = 0; i < MapWidth / 2; ++i) {
        for (int j = 0; j < MapHeight; ++j) {
            mark[i][j] = -1; // -1表示未访问
        }
    }
}

void AI::markPath(const Food& food) {
    // 清空队列
    clearQueue();
    
    // 从食物位置开始
    int foodX = food.x / 2;
    int foodY = food.y;
    mark[foodX][foodY] = 0;
    addToQueue(foodX, foodY, 0);
    
    // 处理队列
    processQueue();
}

void AI::addToQueue(int x, int y, int value) {
    QueueNode* newNode = new QueueNode{x, y, nullptr};
    
    if (queueHead == nullptr) {
        queueHead = queueTail = newNode;
    } else {
        queueTail->next = newNode;
        queueTail = newNode;
    }
    
    mark[x][y] = value;
}

void AI::processQueue() {
    const int dx[] = {0, -1, 1, 0};  // 左右移动
    const int dy[] = {-1, 0, 0, 1};  // 上下移动
    
    while (queueHead != nullptr) {
        int currentX = queueHead->x;
        int currentY = queueHead->y;
        int currentValue = mark[currentX][currentY];
        
        // 检查四个方向
        for (int i = 0; i < 4; ++i) {
            int newX = currentX + dx[i];
            int newY = currentY + dy[i];
            
            // 处理穿墙
            if (newX < 0) newX = (MapWidth / 2) - 1;
            else if (newX >= MapWidth / 2) newX = 0;
            
            if (newY < 0) newY = MapHeight - 1;
            else if (newY >= MapHeight) newY = 0;
            
            // 如果位置有效且未访问
            if (mark[newX][newY] == -1) {
                addToQueue(newX, newY, currentValue + 1);
            }
        }
        
        // 移除已处理的节点
        QueueNode* temp = queueHead;
        queueHead = queueHead->next;
        delete temp;
    }
}

Direction AI::findBestDirection(const SnakeNode* head) {
    int headX = head->x / 2;
    int headY = head->y;
    
    // 四个可能的方向
    struct {
        int dx;
        int dy;
        Direction dir;
    } directions[] = {
        {0, -1, Direction::Up},     // 上
        {-1, 0, Direction::Left},   // 左
        {1, 0, Direction::Right},   // 右
        {0, 1, Direction::Down}     // 下
    };
    
    Direction bestDir = Direction::Right; // 默认向右
    int minValue = INT_MAX;
    
    // 寻找值最小的方向
    for (const auto& dir : directions) {
        int newX = headX + dir.dx;
        int newY = headY + dir.dy;
        
        // 处理穿墙
        if (newX < 0) newX = (MapWidth / 2) - 1;
        else if (newX >= MapWidth / 2) newX = 0;
        
        if (newY < 0) newY = MapHeight - 1;
        else if (newY >= MapHeight) newY = 0;
        
        // 检查是否为有效路径
        if (mark[newX][newY] != INT_MAX && mark[newX][newY] != -1) {
            if (mark[newX][newY] < minValue) {
                minValue = mark[newX][newY];
                bestDir = dir.dir;
            }
        }
    }
    
    return bestDir;
}

bool AI::isValidPosition(int x, int y) {
    // 检查是否在墙内
    if (x <= 0 || x >= MapWidth / 2 - 1) return false;
    if (y <= 0 || y >= MapHeight - 1) return false;
    return true;
}

void AI::clearQueue() {
    while (queueHead != nullptr) {
        QueueNode* temp = queueHead;
        queueHead = queueHead->next;
        delete temp;
    }
    queueTail = nullptr;
}